Skip to content

fix(ci): move CVE scan to separate workflow to fix permission conflict#282

Merged
gaodan-fang merged 1 commit into
mainfrom
fix/split-cve-workflow
Jul 2, 2026
Merged

fix(ci): move CVE scan to separate workflow to fix permission conflict#282
gaodan-fang merged 1 commit into
mainfrom
fix/split-cve-workflow

Conversation

@gaodan-fang

@gaodan-fang gaodan-fang commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator

The reusable workflow (check-code.yaml) called by release-github.yaml cannot have jobs requesting issues:write. Moved check-vulnerabilities to its own workflow with proper permissions and a weekly schedule.

Summary by CodeRabbit

  • New Features

    • Added an automated vulnerability check that runs on pull requests and on a weekly schedule.
    • Security findings are summarized with severity levels, and critical issues are surfaced as warnings.
    • When high-risk issues are found, a tracking issue is created or updated with affected packages and available fixes.
  • Chores

    • Removed the vulnerability-checking step from the main code validation workflow.

The reusable workflow (check-code.yaml) called by release-github.yaml
cannot have jobs requesting issues:write. Moved check-vulnerabilities
to its own workflow with proper permissions and a weekly schedule.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The check-vulnerabilities job is removed from check-code.yaml and reimplemented as a standalone check-vulnerabilities.yaml workflow. The new workflow runs on pull requests and a weekly schedule, performs pip-audit scanning, queries OSV for severity, and creates/updates GitHub issues for critical/high CVEs.

Changes

Vulnerability check workflow relocation

Layer / File(s) Summary
Remove inline vulnerability job
.github/workflows/check-code.yaml
Deletes the check-vulnerabilities job block, so the workflow now proceeds directly from check-plugins-rendered to ui-tests.
New standalone vulnerability workflow
.github/workflows/check-vulnerabilities.yaml
Adds a new workflow triggered on pull requests and weekly schedule that exports dependencies, runs pip-audit, queries OSV for severity scores, classifies critical/high CVEs, creates or updates a labeled GitHub issue, and emits non-blocking warnings.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Scheduler as PR/Schedule Trigger
  participant Workflow as check-vulnerabilities workflow
  participant PipAudit as pip-audit
  participant OSV as OSV API
  participant GitHubIssues as GitHub Issues

  Scheduler->>Workflow: trigger run
  Workflow->>PipAudit: run audit on exported requirements
  PipAudit-->>Workflow: JSON audit results
  Workflow->>OSV: query severity per unique CVE
  OSV-->>Workflow: severity scores
  Workflow->>Workflow: classify critical/high findings
  alt critical or high findings exist
    Workflow->>GitHubIssues: create or update automated security issue
  end
  Workflow->>Workflow: emit warnings for critical CVEs (non-blocking)
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: moving CVE scanning into its own workflow to avoid permission conflicts.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/split-cve-workflow

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@gaodan-fang gaodan-fang merged commit c91bdd0 into main Jul 2, 2026
7 of 8 checks passed

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
.github/workflows/check-vulnerabilities.yaml (1)

93-133: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Resolved-vulnerability case leaves a stale open issue.

The create/update block only executes when critical.length > 0 || high.length > 0. When a later scan comes back clean, any previously opened security,automated issue is neither updated nor closed, so it lingers as an open, out-of-date alert. Consider closing (or commenting on) the existing automated issue when no critical/high CVEs remain.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/check-vulnerabilities.yaml around lines 93 - 133, The
issue is that the automated security issue management in the vulnerability scan
workflow only handles non-empty critical/high results, leaving a previously
created automated issue open when a later scan is clean. Update the logic around
the existing issue lookup in the workflow step to also handle the
zero-vulnerability case by finding the current issue created by the automated
flow and closing it, or otherwise marking it resolved, when both critical and
high arrays are empty. Keep the change centered on the current create/update
block and the existing issue search that uses the automated label.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/check-vulnerabilities.yaml:
- Around line 3-10: The workflow currently lets the vulnerability-filing logic
run on pull_request events, which can fail on forked PRs and create noisy
duplicate issues on normal PRs. Update the check-vulnerabilities workflow so the
issue creation/update logic in the Process results step only runs for scheduled
executions by checking github.event_name in that step, or otherwise make the
pull_request path reporting-only. Keep the change focused around the Process
results github-script and the existing on: trigger block.
- Around line 37-38: The audit-results handling in the workflow’s Node.js
snippet should guard against missing or empty /tmp/audit-results.json before
calling readFileSync and JSON.parse. Update the logic around the existing fs
usage so it first checks the file exists and has content, then only parses when
valid, otherwise skips JSON loading and handles the no-results case gracefully
in the audit step.
- Around line 53-76: The severity scoring logic in the OSV fetch loop currently
relies on non-standard database_specific fields, which can leave CVSS
vulnerabilities at 0. Update the parsing in the uniqueIds processing block to
read the top-level severity[] entries first, convert any CVSS vector information
to a base score, and then fall back to database_specific.cvss_v3 or
database_specific.severity if needed. Keep the existing severityMap assignment
in place, but ensure the score calculation in this fetch path prefers OSV
severity data before the fallback fields.

---

Nitpick comments:
In @.github/workflows/check-vulnerabilities.yaml:
- Around line 93-133: The issue is that the automated security issue management
in the vulnerability scan workflow only handles non-empty critical/high results,
leaving a previously created automated issue open when a later scan is clean.
Update the logic around the existing issue lookup in the workflow step to also
handle the zero-vulnerability case by finding the current issue created by the
automated flow and closing it, or otherwise marking it resolved, when both
critical and high arrays are empty. Keep the change centered on the current
create/update block and the existing issue search that uses the automated label.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 828935d6-5cfe-47b5-a51b-d24287b7a55a

📥 Commits

Reviewing files that changed from the base of the PR and between 2cae2fc and 9a296d5.

📒 Files selected for processing (2)
  • .github/workflows/check-code.yaml
  • .github/workflows/check-vulnerabilities.yaml
💤 Files with no reviewable changes (1)
  • .github/workflows/check-code.yaml

Comment on lines +3 to +10
on:
pull_request:
schedule:
- cron: '0 8 * * 1'

permissions:
contents: read
issues: write

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

pull_request trigger will write GitHub issues from PR context (fails on fork PRs, noisy on same-repo PRs).

The issue create/update in the Process results step runs on every pull_request event when vulns are found. For PRs from forks, GITHUB_TOKEN is downgraded to read-only regardless of the permissions: block, so issues.create/issues.update return 403 — and since this github-script step isn't continue-on-error, the job fails. For same-repo PRs it will create/update the shared security issue on every PR, duplicating the scheduled run.

Consider restricting the issue-filing logic to the scheduled event (e.g. gate the write on github.event_name == 'schedule'), or scope the PR run to reporting-only.

🔧 Example: gate issue writes to scheduled runs
             // Create/update GH issue for high+critical
-            if (critical.length > 0 || high.length > 0) {
+            if ((critical.length > 0 || high.length > 0) && context.eventName === 'schedule') {

Also applies to: 32-33

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/check-vulnerabilities.yaml around lines 3 - 10, The
workflow currently lets the vulnerability-filing logic run on pull_request
events, which can fail on forked PRs and create noisy duplicate issues on normal
PRs. Update the check-vulnerabilities workflow so the issue creation/update
logic in the Process results step only runs for scheduled executions by checking
github.event_name in that step, or otherwise make the pull_request path
reporting-only. Keep the change focused around the Process results github-script
and the existing on: trigger block.

Comment on lines +37 to +38
const fs = require('fs');
const results = JSON.parse(fs.readFileSync('/tmp/audit-results.json', 'utf8'));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Guard against a missing/empty audit-results file.

steps.audit.outcome == 'failure' fires whenever pip-audit exits non-zero, which includes tool errors — not only when vulnerabilities are found. In those cases /tmp/audit-results.json may be absent or empty, and readFileSync/JSON.parse will throw and fail the step. A small existence/parse guard makes this robust.

🛡️ Proposed guard
             const fs = require('fs');
-            const results = JSON.parse(fs.readFileSync('/tmp/audit-results.json', 'utf8'));
+            if (!fs.existsSync('/tmp/audit-results.json')) {
+              console.log('No audit results file found; pip-audit may have errored. Skipping.');
+              return;
+            }
+            let results;
+            try {
+              results = JSON.parse(fs.readFileSync('/tmp/audit-results.json', 'utf8'));
+            } catch (e) {
+              core.warning(`Could not parse audit results: ${e.message}`);
+              return;
+            }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const fs = require('fs');
const results = JSON.parse(fs.readFileSync('/tmp/audit-results.json', 'utf8'));
const fs = require('fs');
if (!fs.existsSync('/tmp/audit-results.json')) {
console.log('No audit results file found; pip-audit may have errored. Skipping.');
return;
}
let results;
try {
results = JSON.parse(fs.readFileSync('/tmp/audit-results.json', 'utf8'));
} catch (e) {
core.warning(`Could not parse audit results: ${e.message}`);
return;
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/check-vulnerabilities.yaml around lines 37 - 38, The
audit-results handling in the workflow’s Node.js snippet should guard against
missing or empty /tmp/audit-results.json before calling readFileSync and
JSON.parse. Update the logic around the existing fs usage so it first checks the
file exists and has content, then only parses when valid, otherwise skips JSON
loading and handles the no-results case gracefully in the audit step.

Comment on lines +53 to +76
for (const id of uniqueIds) {
try {
const resp = await fetch(`https://api.osv.dev/v1/vulns/${id}`);
if (!resp.ok) continue;
const data = await resp.json();
let score = 0;
if (data.database_specific?.cvss_v3) {
score = typeof data.database_specific.cvss_v3 === 'number'
? data.database_specific.cvss_v3
: parseFloat(data.database_specific.cvss_v3) || 0;
}
if (data.database_specific?.severity) {
const sev = data.database_specific.severity.toUpperCase();
if (sev === 'CRITICAL') score = Math.max(score, 9.0);
else if (sev === 'HIGH') score = Math.max(score, 7.0);
}
if (score === 0 && data.affected) {
for (const a of data.affected) {
if (a.database_specific?.cvss_v3) {
score = Math.max(score, parseFloat(a.database_specific.cvss_v3) || 0);
}
}
}
severityMap[id] = score;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

OSV API v1 vulns response severity field schema CVSS_V3 database_specific

💡 Result:

In the OSV (Open Source Vulnerability) schema, the severity of a vulnerability is represented by the severity field, which is an array of objects [1][2]. Each object in this array contains a type and a score [1][2]. The type field specifies the quantitative scoring method used [1][2]. When using CVSS, the type should be set to CVSS_V3 (or CVSS_V2 / CVSS_V4 as appropriate) [2]. The score field is a string containing the CVSS vector string (e.g., "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H") [1]. The database_specific field is a flexible, optional JSON object [2]. It is intended for storing custom or non-standardized metadata that is specific to the database providing the record [2]. It is distinct from the standardized severity field; while some databases might optionally include severity-related metadata within database_specific, such data is not part of the core, machine-readable severity schema [1][2][3]. Summary of relevant fields: - severity: A list of objects, each with a type (e.g., CVSS_V3) and score (e.g., the vector string) [1][2]. - database_specific: A general-purpose JSON structure for database-defined metadata [2][3]. It should not be used as a substitute for the severity field if the goal is to provide standardized, interoperable vulnerability scoring [1][2].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate the workflow and inspect the relevant section with line numbers.
git ls-files .github/workflows/check-vulnerabilities.yaml
sed -n '1,220p' .github/workflows/check-vulnerabilities.yaml

# Find any other OSV parsing or severity handling in the repo.
rg -n "database_specific|severity\\]|CVSS_V3|osv.dev/v1/vulns|cvss_v3" .

Repository: AgentToolkit/altk-evolve

Length of output: 5885


Severity scoring should use OSV severity[] first. database_specific.cvss_v3/severity is non-standard here, so CVSS-based vulns can fall through to 0 and be skipped. Parse the top-level severity entries (CVSS vector → base score) and keep database_specific as a fallback.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/check-vulnerabilities.yaml around lines 53 - 76, The
severity scoring logic in the OSV fetch loop currently relies on non-standard
database_specific fields, which can leave CVSS vulnerabilities at 0. Update the
parsing in the uniqueIds processing block to read the top-level severity[]
entries first, convert any CVSS vector information to a base score, and then
fall back to database_specific.cvss_v3 or database_specific.severity if needed.
Keep the existing severityMap assignment in place, but ensure the score
calculation in this fetch path prefers OSV severity data before the fallback
fields.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant